package danran.dbapi.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import danran.dbapi.common.ApiConfig;
import danran.dbapi.common.ResponseDto;
import danran.dbapi.controller.util.OutputUtil;
import danran.dbapi.core.SqlMeta;
import danran.dbapi.core.engine.DynamicSqlEngine;
import danran.dbapi.domain.DataSource;
import danran.dbapi.domain.Group;
import danran.dbapi.service.ApiConfigService;
import danran.dbapi.service.DataSourceService;
import danran.dbapi.service.GroupService;
import danran.dbapi.utils.JDBCUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Classname ApiConfigController
 * @Description TODO
 * @Date 2022/1/17 16:41
 * @Created by RanCoder
 */
@RestController
@CrossOrigin
@RequestMapping("/apiConfig")
public class ApiConfigController {
    @Autowired
    ApiConfigService apiConfigService;

    @Autowired
    DataSourceService dataSourceService;

    @Autowired
    GroupService groupService;

    @RequestMapping("/add")
    public ResponseDto add(@RequestBody ApiConfig apiConfig) {
        return apiConfigService.add(apiConfig);
    }

    @RequestMapping("/parseParam")
    public ResponseDto parseParam(String sql) {
        try {
            Set<String> set = new DynamicSqlEngine().parseParameter(sql);
//            转化成前端需要的格式
            List<JSONObject> list = set.stream().map(t -> {
                JSONObject object = new JSONObject();
                object.put("value", t);
                return object;
            }).collect(Collectors.toList());
            return ResponseDto.successWithData(list);
        } catch (Exception e) {
            return ResponseDto.fail(e.getMessage());
        }
    }

    @RequestMapping("/getAll")
    public List<ApiConfig> getAll() {
        return apiConfigService.getAll();
    }

//    @RequestMapping("/getAll")
//    public ResponseDto getAll() {
//        return ResponseDto.successWithData(apiConfigService.getAll());
//    }


    //给前端使用的数据结构
    @RequestMapping("/getApiTree")
    public JSONArray getApiTree() {
        return apiConfigService.getAllDetail();
    }

    @RequestMapping("/search")
    public List<ApiConfig> search(String keyword, String field, String groupId) {
        return apiConfigService.search(keyword, field, groupId);
    }

    @RequestMapping("/detail/{id}")
    public ApiConfig detail(@PathVariable String id) {
        return apiConfigService.detail(id);
    }

    @RequestMapping("/delete/{id}")
    public ApiConfig delete(@PathVariable String id) {
        String path = apiConfigService.getPath(id);
        apiConfigService.delete(id, path);
        return null;
    }

    @RequestMapping("/update")
    public ResponseDto update(@RequestBody ApiConfig apiConfig) {
        return apiConfigService.update(apiConfig);
    }

    @RequestMapping("/online/{id}")
    public ApiConfig online(@PathVariable String id) {
        String path = apiConfigService.getPath(id);
        apiConfigService.online(id, path);
        return null;
    }

    @RequestMapping("/offline/{id}")
    public ApiConfig offline(@PathVariable String id) {
        String path = apiConfigService.getPath(id);
        apiConfigService.offline(id, path);
        return null;
    }

    @RequestMapping("/getIPPort")
    public String getIPPort(HttpServletRequest request) throws UnknownHostException {
        return InetAddress.getLocalHost().getHostAddress() + ":" + request.getServerPort();
//        return request.getServerName() + ":" + request.getServerPort();
    }

    @RequestMapping("/getToken")
    public String getToken(String groupId) {
        return apiConfigService.getToken(groupId);
    }

    @RequestMapping("/apiDocs")
    public void apiDocs(String ids, HttpServletResponse response) {
        List<String> idArray = ids == null ? apiConfigService.getAllIPIDs() : Arrays.asList(ids.split(","));
        String docs = apiConfigService.apiDocs(idArray);

        response.setContentType("application/x-msdownload;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment; filename=API docs.md");
        OutputUtil.fileOut(response, docs);
    }

    @RequestMapping("/downloadConfig")
    public void downloadConfig(String ids, HttpServletResponse response) {
        List<String> idArray = ids == null ? apiConfigService.getAllIPIDs() : Arrays.asList(ids.split(","));
        List<ApiConfig> apiConfigs = apiConfigService.selectBatch(idArray);

        String s = JSON.toJSONString(apiConfigs);
        response.setContentType("application/x-msdownload;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment; filename=api_config.json");
        OutputUtil.fileOut(response, s);
    }


    @RequestMapping("/downloadGroupConfig")
    public void downloadGroupConfig(String ids, HttpServletResponse response) {
        List<String> collect = ids == null ? groupService.getAllGroupIds() : Arrays.asList(ids.split(","));
        List<Group> list = groupService.selectBatch(collect);
        String s = JSON.toJSONString(list);
        response.setContentType("application/x-msdownload;charset=utf-8");

        OutputUtil.fileOut(response, s);
    }

    @RequestMapping(value = "/import", produces = "application/json;charset=UTF-8")
    public void uploadFile(@RequestParam("file") MultipartFile file) throws IOException {

        String s = IOUtils.toString(file.getInputStream(), StandardCharsets.UTF_8);
        List<ApiConfig> configs = JSON.parseArray(s, ApiConfig.class);
        configs.forEach(t -> t.setStatus(0));
        apiConfigService.insertBatch(configs);

    }

    @RequestMapping(value = "/importGroup", produces = "application/json;charset=UTF-8")
    public void importGroup(@RequestParam("file") MultipartFile file) throws IOException {

        String s = IOUtils.toString(file.getInputStream(), StandardCharsets.UTF_8);
        List<Group> configs = JSON.parseArray(s, Group.class);
        groupService.insertBatch(configs);

    }

    @RequestMapping("/sql/execute")
    public ResponseDto executeSql(String datasourceId, String sql, String params) {
        try {
            DataSource dataSource = dataSourceService.detail(datasourceId);
            Map<String, Object> map = JSON.parseObject(params, Map.class);
            SqlMeta sqlMeta = new DynamicSqlEngine().parse(sql, map);
            Object data = JDBCUtil.executeSql(dataSource, sqlMeta.getSql(), sqlMeta.getJdbcParamValues());
            return ResponseDto.successWithData(data);
        } catch (Exception e) {
            return ResponseDto.fail(e.getMessage());
        }

    }

    @RequestMapping("/parseDynamicSql")
    public ResponseDto parseDynamicSql(String sql, String params) {
        try {
            Map<String, Object> map = JSON.parseObject(params, Map.class);
            SqlMeta sqlMeta = new DynamicSqlEngine().parse(sql, map);
            return ResponseDto.successWithData(sqlMeta);
        } catch (Exception e) {
            return ResponseDto.fail(e.getMessage());
        }

    }
}
